//
//  Message.cpp
//  WiFiMACSim
//
//  Created by Christopher Kemsley on 3/31/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#include "Message.hpp"
#include "Exception.hpp"
#include "System.hpp"

SimNamespaceBegin



std::ostream & operator<< ( std::ostream & str , Message const & msg )
	{
	str << "<Message 0x"<<&msg<<"> {" ;
	
	str << "from='" << msg.sender << "'" ;
	str << " to='" << msg.target << "'" ;
	
	str << " in-flight-slots=[" << msg.firstSlot << "," << msg.lastSlot << "]" ;
	
	str << " type='" << Message::typeString(msg.type) << "'" ;
	str << " status='" << Message::statusString(msg.status) << "'" ;
	
	str << "}" ;
	
	return str ;
	}


Message :: Message ( ID const & inSender , ID const & inTarget , Type inType , UInteger inDuration )
:	sender			( inSender )
,	target			( inTarget )
,	type			( inType )
,	duration		( inDuration )
,	firstSlot		( UIntegerMax )
,	lastSlot		( UIntegerMax )
,	isInFlight		( false )
,	remainingDuration(inDuration)
,	status			( kStatusUnhandled )
,	_retainCount ( 1 )
	{
	
	}
Message :: ~Message ()
	{
	
	}


void	Message :: retain ()
	{
	_retainCount++ ;
	}
void	Message :: release ()
	{
	if ( _retainCount == 0 )
		{
		ThrowException ( "Message" , "Released with retain count of zero (double-released)" , __FILE__,__LINE__ ) ;
		}
	else if ( _retainCount != 1 )
		_retainCount -- ;
	else
		delete this ;
	}



std::string const&	Message :: typeString ( Type const & type )
	{
	switch ( type )
		{
			case kTypeData : {
				static std::string const name ( "Data" ) ;
				return name ;
			} break ;
			
			case kTypeRTS : {
				static std::string const name ( "RTS" ) ;
				return name ;
			} break ;
			
			case kTypeCTS : {
				static std::string const name ( "CTS" ) ;
				return name ;
			} break ;
			
			case kTypeACK : {
				static std::string const name ( "Ack" ) ;
				return name ;
			} break ;
			
			default: {
				static std::string const name ( "(unknown)" ) ;
				return name ;
			} break ;
		}
	}
std::string const&	Message :: statusString ( Status const & type )
	{
	switch ( type )
		{
			case kStatusUnhandled : {
				static std::string const name ( "not-handled" ) ;
				return name ;
			} break ;
			
			case kStatusSuccessful : {
				static std::string const name ( "Received-in-whole" ) ;
				return name ;
			} break ;
			
			case kStatusFailedToReceive : {
				static std::string const name ( "Corrupted-at-receiver" ) ;
				return name ;
			} break ;
			
			default: {
				static std::string const name ( "(unknown)" ) ;
				return name ;
			} break ;
		}
	}


SimNamespaceEnd
